const mqtt = require('mqtt');
const fs = require('fs');
//const ffmpeg = require('fluent-ffmpeg');

class MqttClient {
  constructor(options, connection) {
    this.client = mqtt.connect(options.url, options);
    this.directMqtt = [];//储存没有发出的指令
    this.devices = {};//储存设备信息
    this.devicesId = [];//储存设备ID
    this.db = connection;
    this.reconnectCount = 0;
    // 消息存储队列（按设备ID存储）
    //this.messageQueue = new Map()
    this.messageQueue = [];
    // 心跳检测标志
    this.heartbeatFlag = false;
    // 重连标志
    this.reconnectFlag = false;
    // 心跳计数器
    this.heartbeattimecount = 0;
    this.init();
  }

  init() {
    this.client.on('connect', () => this.onConnect());
    this.client.on('error', (err) => this.onError(err));
    this.client.on('disconnect', () => this.onDisconnect());
    this.client.on('message', (topic, message) => this.onMessage(topic, message));
    this.client.on('reconnect', () => this.onReconnect());
    this.client.on('reconnect', () => this.onReconnectFailed());
    this.client.subscribe('sensor_data');
    this.client.subscribe('yi_chang_flag');
    this.client.subscribe('heartbeat');
    this.client.subscribe('sensorData');
    this.client.subscribe('power');
  }

  onConnect() {
    console.log('mqtt服务器连接成功');
    if (this.reconnectFlag /*&& this.isDirectExisted */) {
      //this.sendDirect();
      //this.isDirectExisted = false;
      this.reconnectFlag = false;
      //this.directMqtt = {};

    }
  }

  onError(err) {
    console.log('连接失败', err);
    // this.stopHeartbeat();
  }

  onDisconnect() {
    console.log('连接断开');
    this.stopHeartbeat();
  }

  onMessage(topic, message) {
    let data;
    try {
      data = JSON.parse(message);
    } catch (err) {
      return;
    }
    if (topic === 'sensorData') {
      this.insertData([0, data.wen_du_1, data.shi_du_1, data.light1, data.I_1, data.V_1, data.time]);
      this.insertData([1, data.wen_du_2, data.shi_du_2, data.light2, data.I_2, data.V_2, data.time]);
      this.insertData([2, data.wen_du_3, data.shi_du_3, data.light3, data.I_3, data.V_3, data.time]);
    }
    else if (topic === 'power') {
      const query = 'insert into t_other_data (d_no,field1,field2,c_time) values (?, ?, ?,?)';
      this.db.query(query, [0, data.hao_dian_liang_1, data.p_1, data.time], (err) => {
        if (err) {
          console.log(err);
        } else {
          //console.log('插入成功');
        }
      });
    }
    else if (topic == 'yi_chang_flag') {
      let sensorTypes = ["yan_wu", "shui_wei", "wen_du"];
      let sensorCodes = { "yan_wu": "烟雾", "shui_wei": "水位", "wen_du": "温度" };
      let errorMsg=["过高","过低"]
      sensorTypes.forEach((sensorType, index) => {
        if (data[`${sensorType}_${index + 1}_flag`] != 0 && data[`${sensorType}_${index + 1}_flag`] != undefined) {
          this.inserWarntData([data.time, `${sensorCodes[sensorType]}报警`, index,`${sensorCodes[sensorType]}${errorMsg[data[`${sensorType}_${index + 1}_flag`]-1]}`]);
        }
      });
    }
  }

  onReconnect() {
    this.reconnectCount++;
    console.log(`第${this.reconnectCount}次重连中`);
    this.reconnectFlag = true;
  }

  onReconnectFailed() {
    if (this.reconnectCount <= 5) {
      this.client.reconnect();
      this.reconnectCount++;
    } else {
      console.log('重连失败');
    }
  }

  publish(topic, data) {
    //心跳检测离线时消息存储
    setTimeout(() => {
      this.client.publish(topic, JSON.stringify(data), { qos: 0, retain: false });
    }, 30)
  }

  heartbeatCheck() {
    this.heartbeattimecount++;
    if (this.heartbeattimecount > 5) {
      this.heartbeatFlag = false;
      console.log('心跳超时，断开连接');
    }
  }

  //发送未发送出去的指令
  sendDirect_done() {
    if (this.directMqtt.length > 0) {
      let directMqtt = this.directMqtt.shift();
      this.client.publish(directMqtt.topic, JSON.stringify(directMqtt.data), { qos: 0, retain: false });
      setTimeout(() => {
        this.sendDirect_done();
      }, 300);
    }
  }

  insertData(values) {
    const query = 'insert into t_data (d_no,field1,field2,field3,field4,field5,c_time) values (?, ?, ?, ?,?,?,?)';
    this.db.query(query, values, (err) => {
      if (err) {
        console.log(err);
      } else {
        //console.log('插入成功');
      }
    });
  }

  inserWarntData(values) {
    this.db.query('insert into t_error_msg (c_time,type,e_no,e_msg) values (?,?,?,?)', values, (err) => {
      if (err) {
        console.log(err);
      } else {
        //console.log('插入成功');
      }
      this.client.publish('sensorData', JSON.stringify({ 'led1': 'on' }));
    });
  }

  inserthistoryData(data, topic) {
    //MQTT发送时间格式为HH:MM:SS，数据库格式为YYYY-MM-DD HH:MM:SS
    //补充MQTT发送的时间data.c_time HH:MM:SS格式为YYYY-MM-DD HH:MM:SS格式
    if (data.time === undefined) {
      //如果没有传时间，则取系统时间HH:MM:SS格式
      data.time = new Date().toLocaleTimeString().replace(/:\d{1,2}$/, '');
    }

    const now = new Date();
    const [hours, minutes, seconds] = data.time.split(':').map(Number);
    // 直接构造日期对象（使用本地时间）
    const localDate = new Date(
      now.getFullYear(),
      now.getMonth(),
      now.getDate(),
      hours,
      minutes,
      seconds
    );
    let query = '';
    let values = [];
    if (data.status == "1") {
      query = 'update books_history_data set end_time =? where book_id =? and reader_id =?';
      values = [formatLocalTime(localDate), data.PID, data.PID];
    }
    else {
      query = 'insert into books_history_data (reader_id,book_id,start_time,net) values (?, ?, ?,?)';
      values = [data.PID, data.PID, formatLocalTime(localDate), topic];
    }
    this.db.query(query, values, (err) => {
      if (err) {
        console.log(err);
      } else {
        console.log('成功');
      }
    });

  }
}

// 手动格式化避免时区转换
function formatLocalTime(date) {
  const pad = n => n.toString().padStart(2, '0');
  return `${date.getFullYear()}-${pad(date.getMonth() + 1)}-${pad(date.getDate())} ` +
    `${pad(date.getHours())}:${pad(date.getMinutes())}:${pad(date.getSeconds())}`;
}

module.exports = MqttClient;